package com.example.springboot.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.springboot.common.Constants;
import com.example.springboot.common.Result;
import com.example.springboot.config.schedule.CacheManager;
import com.example.springboot.entity.dto.resp.AlarmFarmInfoRespDTO;
import com.example.springboot.entity.dto.resp.MetAlarmInfoRespDTO;
import com.example.springboot.entity.AlarmMeasure;
import com.example.springboot.entity.ComFarm;
import com.example.springboot.entity.MetAlarm;
import com.example.springboot.entity.User;
import com.example.springboot.exception.ServiceException;
import com.example.springboot.mapper.AlarmMeasureMapper;
import com.example.springboot.mapper.MetAlarmMapper;
import com.example.springboot.mapper.UserMapper;
import com.example.springboot.service.IComFarmService;
import com.example.springboot.service.IMetAlarmService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.springboot.service.IUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate;

import javax.swing.text.html.Option;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import static java.time.format.DateTimeFormatter.ofPattern;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author dhn
 * @since 2024-04-11
 */
@Service
@RequiredArgsConstructor
public class MetAlarmServiceImpl extends ServiceImpl<MetAlarmMapper, MetAlarm> implements IMetAlarmService {

    private final IComFarmService comFarmService;

    private final IUserService iUserService;

    private final MetAlarmMapper metAlarmMapper;

    private final RestTemplate restTemplate;

    private final UserMapper userMapper;

    private final AlarmMeasureMapper alarmMeasureMapper;


    @Value("${wx.mp.appid}")
    private String appid;

    @Value("${wx.mp.appSecret}")
    private String appSecret;

    @Value("${wx.mp.alarmModelId}")
    private String alarmModelId;


    @Override
//    public void checkAndSendAlarms() {
//        Date date = new Date();
//
//        //根据当前时间去判断开始时间到结束时间的范围内没有被推送过的预警
//        LambdaQueryWrapper<MetAlarm> queryWrapper = Wrappers.lambdaQuery(MetAlarm.class)
//                .le(MetAlarm::getIssueTime, date)
//                .ge(MetAlarm::getIssueEndTime, date)
//                .eq(MetAlarm::getIsFlag, "0");
//        List<MetAlarm> metAlarms = baseMapper.selectList(queryWrapper);
//        //使用集合来装预警的地区，做到不重复推送消息
//        AtomicReference<Set<AlarmFarmInfoRespDTO>> comFarmAlarmSet = new AtomicReference<>(new HashSet<>());
////        AtomicReference<Set<MetAlarm>> metAlarmSet = new AtomicReference<>(new HashSet<>());
//        metAlarms.forEach(metAlarm -> {
//            String alarmRange = metAlarm.getAlarmRange();
//            String[] ranges = alarmRange.split(",");
//            Arrays.stream(ranges).forEach(range -> {
//                LambdaQueryWrapper<ComFarm> comFarmLambdaQueryWrapper = Wrappers.lambdaQuery(ComFarm.class)
//                        .like(ComFarm::getAddress, range);
//                List<ComFarm> comFarmList = comFarmService.list(comFarmLambdaQueryWrapper);
//                comFarmList.forEach(comFarm -> {
//                    AlarmFarmInfoRespDTO alarmFarmInfo = AlarmFarmInfoRespDTO.builder()
//                            .farmId(comFarm.getFarmId())
//                            .farmAddress(comFarm.getFarmAddress())
//                            .farmName(comFarm.getFarmName())
//                            .metAlarm(metAlarm)
//                            .jkRole(comFarm.getJkRole())
//                            .build();
//                    comFarmAlarmSet.get().add(alarmFarmInfo);
//                });
//            });
//        });
////        metAlarmSet.get().addAll(metAlarms);
//
//        if (metAlarms.size() != 0) {
//            String accessToken = CacheManager.getAccessToken();
//            Set<MetAlarm> sendSubMetAlarm = new HashSet<>();
//            LambdaQueryWrapper<User> userLambdaQueryWrapper = Wrappers.lambdaQuery(User.class)
//                    .eq(User::getIsDisabled, "0");
////                    .eq(User::getIsSubscribe, "1");
//            //获取所有用户
//            List<User> userList = iUserService.list(userLambdaQueryWrapper);
//            userList.forEach(user -> {
//                if (user.getOpenid() != null) {
//                    if (Objects.equals(user.getRole(), "ROLE_ADMIN") || Objects.equals(user.getRole(), "ROLE_DW_USER")) {
//                        //管理员、电网用户
//                        comFarmAlarmSet.get().forEach(metAlarm -> {
//                            sendSubMetAlarm.add(metAlarm.getMetAlarm());
//                            sendAlarmMsgToUser(accessToken, user.getOpenid(), metAlarm.getMetAlarm().getType(), metAlarm.getMetAlarm().getAlarmLevel(), metAlarm.getMetAlarm().getAlarmSignal(), metAlarm.getMetAlarm(), user);
//                        });
//                    } else if (Objects.equals(user.getRole(), "ROLE_JK_USER")) {
//                        Set<MetAlarm> metAlarmCurUser = new HashSet<>();
//                        //集控中心用户
//                        comFarmAlarmSet.get().forEach(farmAlarm -> {
//                            if (Objects.equals(farmAlarm.getJkRole(), user.getJkRole())) {
//                                metAlarmCurUser.add(farmAlarm.getMetAlarm());
//                            }
//                        });
//                        metAlarmCurUser.forEach(each -> {
//                            sendSubMetAlarm.add(each);
//                            sendAlarmMsgToUser(accessToken, user.getOpenid(), each.getType(), each.getAlarmLevel(), each.getAlarmSignal(), each, user);
//                        });
//
//                    } else if (Objects.equals(user.getRole(), "ROLE_FARM_USER")) {
//                        //电站用户
//                        comFarmAlarmSet.get().forEach(farmAlarm -> {
//                            if (Objects.equals(farmAlarm.getFarmId(), user.getFarmId())) {
//                                sendSubMetAlarm.add(farmAlarm.getMetAlarm());
//                                sendAlarmMsgToUser(accessToken, user.getOpenid(), farmAlarm.getMetAlarm().getType(), farmAlarm.getMetAlarm().getAlarmLevel(), farmAlarm.getMetAlarm().getAlarmSignal(), farmAlarm.getMetAlarm(), user);
//                            }
//                        });
//                    }
//                }
//            });
//            List<MetAlarm> metAlarmList = new ArrayList<>(sendSubMetAlarm);
//            if (metAlarmList.size() != 0) {
//                metAlarmMapper.updateBatchAlarmInfo(metAlarmList);
//            }
//        }
//
//
//    }

    public void checkAndSendAlarms() {
        Date date = new Date();
        List<MetAlarm> metAlarms = baseMapper.selectList(Wrappers.lambdaQuery(MetAlarm.class)
                .le(MetAlarm::getIssueTime, date)
                .ge(MetAlarm::getIssueEndTime, date)
                .eq(MetAlarm::getIsFlag, "0"));

        // 预加载所有的ComFarm数据
        List<ComFarm> allComFarms = comFarmService.list(Wrappers.lambdaQuery(ComFarm.class).isNotNull(ComFarm::getAddress));

        Set<AlarmFarmInfoRespDTO> alarmFarmInfoSet = new HashSet<>();
        for (MetAlarm metAlarm : metAlarms) {
            String[] ranges = metAlarm.getAlarmRange().split(",");
            for (String range : ranges) {
                List<ComFarm> filteredFarms = allComFarms.stream()
                        .filter(farm -> farm.getAddress().contains(range))
                        .collect(Collectors.toList());
                for (ComFarm farm : filteredFarms) {
                    AlarmFarmInfoRespDTO alarmFarmInfo = AlarmFarmInfoRespDTO.builder()
                            .farmId(farm.getFarmId())
                            .farmAddress(farm.getFarmAddress())
                            .farmName(farm.getFarmName())
                            .metAlarm(metAlarm)
                            .jkRole(farm.getJkRole())
                            .build();
                    alarmFarmInfoSet.add(alarmFarmInfo);
                }
            }
        }

        if (!alarmFarmInfoSet.isEmpty()) {
            String accessToken = CacheManager.getAccessToken();
            Set<MetAlarm> sendSubMetAlarm = new HashSet<>();
            List<User> userList = iUserService.list(Wrappers.lambdaQuery(User.class)
                    .eq(User::getIsDisabled, "0"));

            for (User user : userList) {
                if (user.getOpenid() != null) {
                    for (AlarmFarmInfoRespDTO alarmInfo : alarmFarmInfoSet) {
                        MetAlarm metAlarm = alarmInfo.getMetAlarm();
                        // 判断用户角色和地区是否匹配
                        if ((Objects.equals(user.getRole(), "ROLE_ADMIN") || Objects.equals(user.getRole(), "ROLE_DW_USER")) ||
                                (Objects.equals(user.getRole(), "ROLE_JK_USER") && Objects.equals(alarmInfo.getJkRole(), user.getJkRole())) ||
                                (Objects.equals(user.getRole(), "ROLE_FARM_USER") && Objects.equals(alarmInfo.getFarmId(), user.getFarmId()))) {
                            sendSubMetAlarm.add(metAlarm);
                            sendAlarmMsgToUser(accessToken, user.getOpenid(), metAlarm.getType(), metAlarm.getAlarmLevel(), metAlarm.getAlarmSignal(), metAlarm, user);
                        }
                    }
                }
            }

            if (!sendSubMetAlarm.isEmpty()) {
                metAlarmMapper.updateBatchAlarmInfo(new ArrayList<>(sendSubMetAlarm));
            }
        }
    }


//    @Override
//    public Result getMetAlarmInfoByUser(String id) {
//        User user = userMapper.selectById(id);
//        if (user == null || Objects.equals(user.getIsDisabled(), "1")) {
//            throw new ServiceException(Constants.CODE_700, "当前访问权限不够，请联系管理员");
//        }
//        String role = user.getRole();
//        Date date = new Date();
//        //根据当前时间去判断开始时间到结束时间的范围内没有被推送过的预警
//        LambdaQueryWrapper<MetAlarm> queryWrapper = Wrappers.lambdaQuery(MetAlarm.class)
//                .le(MetAlarm::getIssueTime, date)
//                .ge(MetAlarm::getIssueEndTime, date);
//        List<MetAlarm> metAlarms = baseMapper.selectList(queryWrapper);
//        AtomicReference<Set<MetAlarmInfoRespDTO>> metAlarmSetList = new AtomicReference<>(new HashSet<>());
//        metAlarms.forEach(metAlarm -> {
//            LambdaQueryWrapper<AlarmMeasure> alarmMeasureWrapper = Wrappers.lambdaQuery(AlarmMeasure.class)
//                    .eq(AlarmMeasure::getAlarmType, metAlarm.getType())
//                    .eq(AlarmMeasure::getAlarmSignal, metAlarm.getAlarmSignal());
//            AlarmMeasure alarmMeasure = alarmMeasureMapper.selectOne(alarmMeasureWrapper);
//            if(ObjectUtil.isNotEmpty(alarmMeasure)){
//                alarmMeasure.setMeasure(alarmMeasure.getMeasure().replaceAll("\n", "<br>"));
//            }
//            SimpleDateFormat sdf = new SimpleDateFormat();
//            sdf.applyPattern("yyyy-MM-dd HH:mm");
//            String pubTime = sdf.format(metAlarm.getIssueTime());
//            String endTime = sdf.format(metAlarm.getIssueEndTime());
//            String alarmRange = metAlarm.getAlarmRange();
//            String[] ranges = alarmRange.split(",");
//            List<String> farmNameList = new ArrayList<>();
//            if(Objects.equals(role, "ROLE_ADMIN")|| Objects.equals(role, "ROLE_DW_USER")){
//                Arrays.stream(ranges).forEach(range -> {
//                    LambdaQueryWrapper<ComFarm> comFarmLambdaQueryWrapper = Wrappers.lambdaQuery(ComFarm.class)
//                            .like(ComFarm::getAddress, range);
//                    List<ComFarm> comFarmList = comFarmService.list(comFarmLambdaQueryWrapper);
//                    List<String> farmList = comFarmList.stream().map(ComFarm::getFarmName).collect(Collectors.toList());
//                    farmNameList.addAll(farmList);
//                });
//            }
//            else if (Objects.equals(role,"ROLE_JK_USER")){
//                Arrays.stream(ranges).forEach(range -> {
//                    LambdaQueryWrapper<ComFarm> comFarmLambdaQueryWrapper = Wrappers.lambdaQuery(ComFarm.class)
//                            .eq(ComFarm::getJkRole,user.getJkRole())
//                            .like(ComFarm::getAddress, range);
//                    List<ComFarm> comFarmList = comFarmService.list(comFarmLambdaQueryWrapper);
//                    List<String> farmList = comFarmList.stream().map(ComFarm::getFarmName).collect(Collectors.toList());
//                    farmNameList.addAll(farmList);
//                });
//            }
//            else if(Objects.equals(role,"ROLE_FARM_USER")){
//                Arrays.stream(ranges).forEach(range -> {
//                    LambdaQueryWrapper<ComFarm> comFarmLambdaQueryWrapper = Wrappers.lambdaQuery(ComFarm.class)
//                            .eq(ComFarm::getFarmId,user.getFarmId())
//                            .like(ComFarm::getAddress, range);
//                    List<ComFarm> comFarmList = comFarmService.list(comFarmLambdaQueryWrapper);
//                    List<String> farmList = comFarmList.stream().map(ComFarm::getFarmName).collect(Collectors.toList());
//                    farmNameList.addAll(farmList);
//                });
//            }
//            else{
//                throw new ServiceException(Constants.CODE_600, "用户角色异常，请联系管理员", Collections.emptyList());
//            }
//            String farmStringList = farmNameList.stream().map(Objects::toString).collect(Collectors.joining(","));
//            MetAlarmInfoRespDTO alarmInfoRespDTO = MetAlarmInfoRespDTO.builder()
//                    .alarmLevel(metAlarm.getAlarmLevel())
//                    .alarmRange(farmStringList)
//                    .alarmSignal(metAlarm.getAlarmSignal())
//                    .type(metAlarm.getType())
//                    .pubUnit(metAlarm.getPubUnit())
//                    .content(metAlarm.getContent())
//                    .measure(alarmMeasure==null?"":alarmMeasure.getMeasure())
//                    .issueTime(pubTime)
//                    .issueEndTime(endTime)
//                    .build();
//            metAlarmSetList.get().add(alarmInfoRespDTO);
//        });
//        if (Objects.equals(role, "ROLE_ADMIN") || Objects.equals(role, "ROLE_DW_USER")) {
//            if (metAlarmSetList.get().size() == 0) {
//                throw new ServiceException(Constants.CODE_600, "当前没有预警信息", Collections.emptyList());
//            }
//            return Result.success(metAlarmSetList);
//        }
//        if (Objects.equals(role, "ROLE_JK_USER")) {
//            if (metAlarmSetList.get().size() == 0) {
//                throw new ServiceException(Constants.CODE_600, "当前没有预警信息", Collections.emptyList());
//            }
//            return Result.success(metAlarmSetList);
//        }
//        if (Objects.equals(role, "ROLE_FARM_USER")) {
//            if (metAlarmSetList.get().size() == 0) {
//                throw new ServiceException(Constants.CODE_600, "当前没有预警信息", Collections.emptyList());
//            }
//            return Result.success(metAlarmSetList);
//        }
//        throw new ServiceException(Constants.CODE_600, "未知异常");
//
//    }

    @Override
    public Result getMetAlarmInfoByUser(String id) {
        User user = userMapper.selectById(id);
        if (user == null || Objects.equals(user.getIsDisabled(), "1")) {
            throw new ServiceException(Constants.CODE_700, "当前访问权限不够，请联系管理员");
        }
        String role = user.getRole();
        Date date = new Date();

        List<MetAlarm> metAlarms = baseMapper.selectList(Wrappers.lambdaQuery(MetAlarm.class)
                .le(MetAlarm::getIssueTime, date)
                .ge(MetAlarm::getIssueEndTime, date).orderByDesc(MetAlarm::getIssueTime));
        // 预加载ComFarm数据
        List<ComFarm> allComFarms = comFarmService.list(Wrappers.lambdaQuery(ComFarm.class).isNotNull(ComFarm::getAddress));

        Set<MetAlarmInfoRespDTO> metAlarmSetList = new LinkedHashSet<>();
        for (MetAlarm metAlarm : metAlarms) {
            AlarmMeasure alarmMeasure = alarmMeasureMapper.selectOne(Wrappers.lambdaQuery(AlarmMeasure.class)
                    .eq(AlarmMeasure::getAlarmType, metAlarm.getType())
                    .eq(AlarmMeasure::getAlarmSignal, metAlarm.getAlarmSignal()));
            if (alarmMeasure != null) {
                alarmMeasure.setMeasure(alarmMeasure.getMeasure().replaceAll("\n", "<br>"));
            }

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            String pubTime = sdf.format(metAlarm.getIssueTime());
            String endTime = sdf.format(metAlarm.getIssueEndTime());

            String[] ranges = metAlarm.getAlarmRange().split(",");
            Set<String> farmNameList = new LinkedHashSet<>();
            for (String range : ranges) {
                // 执行模糊匹配
                List<String> farmNames = allComFarms.stream()
                        .filter(farm -> farm.getAddress().contains(range) &&
                                ((Objects.equals(role, "ROLE_ADMIN") || Objects.equals(role, "ROLE_DW_USER")) ||
                                        (Objects.equals(role, "ROLE_JK_USER") && Objects.equals(farm.getJkRole(), user.getJkRole())) ||
                                        (Objects.equals(role, "ROLE_FARM_USER") && Objects.equals(farm.getFarmId(), user.getFarmId()))))
                        .map(ComFarm::getFarmName)
                        .collect(Collectors.toList());
                farmNameList.addAll(farmNames);
            }
            if(farmNameList.isEmpty()){
                continue;
            }

            String farmStringList = String.join(",", farmNameList);
            MetAlarmInfoRespDTO alarmInfoRespDTO = MetAlarmInfoRespDTO.builder()
                    .alarmLevel(metAlarm.getAlarmLevel())
                    .alarmRange(farmStringList)
                    .alarmSignal(metAlarm.getAlarmSignal())
                    .type(metAlarm.getType())
                    .pubUnit(metAlarm.getPubUnit())
                    .content(metAlarm.getContent())
                    .measure(alarmMeasure == null ? "" : alarmMeasure.getMeasure())
                    .issueTime(pubTime)
                    .issueEndTime(endTime)
                    .build();
            metAlarmSetList.add(alarmInfoRespDTO);
        }

        if (metAlarmSetList.isEmpty()) {
            throw new ServiceException(Constants.CODE_600, "当前没有预警信息", new ArrayList<>());
        }
        return Result.success(metAlarmSetList);
    }




    public void sendAlarmMsgToUser(String accessToken, String userOpenId, String alarmType, String alarmLevel, String alarmSignal, MetAlarm metAlarm, User user) {
        int retryCount = 0; // 记录重试次数
        while (retryCount < 2) { // 允许一次重试
            String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + accessToken;
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            Date date = new Date();
            String pubTime = sdf.format(date);

            Map<String, Map<String, String>> data = buildMessageData(alarmType, alarmLevel, alarmSignal, pubTime);

            Map<String, Object> body = new HashMap<>();
            body.put("touser", userOpenId);
            body.put("template_id", alarmModelId); // 确保这个变量被定义和初始化
            body.put("data", data);
//            String page = "pages/weather/warning/warning?type=1";
            String page = "pagesQxxx/warningSign?type=1";
            body.put("page", page);
            body.put("miniprogram_state", "formal");

            HttpEntity<Map<String, Object>> request = new HttpEntity<>(body, headers);
            try {
                ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, request, String.class);
                if (response.getStatusCode() == HttpStatus.OK) {
                    Map<String, Object> responseMap = JSONUtil.toBean(response.getBody(), Map.class);
                    if (responseMap.containsKey("errcode") && (Integer) responseMap.get("errcode") != 0) {
                        Integer errCode = (Integer) responseMap.get("errcode");
                        if (errCode == 40001 || errCode == 42001) { // Token expired
                            accessToken = CacheManager.refreshAccessToken(); // Refresh token
                            retryCount++;
                            continue; // Retry with new token
                        } else if (errCode == 40003 || errCode == 43101) { // Handle specific WeChat errors
                            handleWechatResponse(responseMap, user);
                            break;
                        }
                    }
                    System.out.println("Message sent successfully.");
                    break; // Exit loop on success
                } else {
                    System.out.println("Failed to send message: HTTP status " + response.getStatusCode());
                    break; // Exit loop on HTTP error other than token issues
                }
            } catch (HttpClientErrorException | HttpServerErrorException e) {
                System.err.println("HTTP error occurred: " + e.getStatusCode() + " " + e.getResponseBodyAsString());
                break; // Exit loop on client or server HTTP error
            } catch (Exception e) {
                System.err.println("An error occurred: " + e.getMessage());
                break; // Exit loop on other exceptions
            }
        }
    }


    private void handleWechatResponse(Map<String, Object> responseMap, User user) {
        if (responseMap.containsKey("errcode") && !responseMap.get("errcode").equals(0)) {
            Integer errCode = (Integer) responseMap.get("errcode");
            String errMsg = (String) responseMap.get("errmsg");
            switch (errCode) {
                case 40003:
                    System.err.println("Invalid openid, check the provided openid: " + errMsg);
//                    if (user.getIsSubscribe() != null && user.getIsSubscribe().equals("1")) {
//                        LambdaUpdateWrapper<User> updateWrapper = Wrappers.lambdaUpdate(User.class)
//                                .eq(User::getId, user.getId())
//                                .set(User::getIsSubscribe, "0");
//                        userMapper.update(null, updateWrapper);
//                    }
                    break;
                case 43101:
                    System.err.println("Invalid openid, check the provided openid: " + errMsg);
//                    if (user.getIsSubscribe() != null && user.getIsSubscribe().equals("1")) {
//                        LambdaUpdateWrapper<User> updateWrapper = Wrappers.lambdaUpdate(User.class)
//                                .eq(User::getId, user.getId())
//                                .set(User::getIsSubscribe, "0");
//                        userMapper.update(null, updateWrapper);
//                    }
                    break;
                // 添加更多错误处理案例
                default:
//                    System.err.println("Invalid openid, check the provided openid: " + errMsg);
//                    if (user.getIsSubscribe() != null && user.getIsSubscribe().equals("1")) {
//                        LambdaUpdateWrapper<User> updateWrapper = Wrappers.lambdaUpdate(User.class)
//                                .eq(User::getId, user.getId())
//                                .set(User::getIsSubscribe, "0");
//                        userMapper.update(null, updateWrapper);
//                    }
                    break;
            }
        } else {
            System.out.println("Message sent successfully.");
        }
    }

    private Map<String, Map<String, String>> buildMessageData(String category, String level, String content, String time) {
        Map<String, Map<String, String>> data = new HashMap<>();
        data.put("phrase1", createDataItem(category));
        data.put("phrase2", createDataItem(level));
        data.put("thing3", createDataItem(content));
        data.put("date4", createDataItem(time));
        return data;
    }

    private Map<String, String> createDataItem(String value) {
        Map<String, String> item = new HashMap<>();
        item.put("value", value);
        return item;
    }


}
